/*
 * chapter_13.cpp
 * 进入第三部分：类设计者的工具
 * 13章：拷贝控制
 * 14章：操作重载和类型转换
 * 15章：面向对象程序设计
 * 16章：模板和泛型编程
 *  Created on: 2020年11月29日
 *      Author: san
 */

#include <iostream>


#include "StrBlobPtr.h"
#include "HasPtr.h"
#include "Message.h"
#include "StrVec.h"
#include "String.h"
#include "Foo.h"


void t13_3()
{
	// 拷贝构造函数
	// weak_ptr不会增加引用计数
	StrBlob sb1({"hello", " world!"});
	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;
	StrBlob sb2(sb1);
	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;

	StrBlobPtr sbp1(sb1);
	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;
	StrBlobPtr sbp2(sbp1);
	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;
}

void t13_7()
{
	/*
	 * 赋值构造函数
	 */
	StrBlob sb1({"hello", " world!"});
	StrBlob sb2({"hello", " cpp!"});
	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;

	sb2 = sb1;
	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;

}

void t13_10()
{
	StrBlob* sb1 = new StrBlob({"hello", " world!"});
//	std::cout << "shared_ptr's count: " << sb1.getDataCount() << std::endl;
	{
//		StrBlob sb1({"hello", " world!"});
		std::cout << "shared_ptr's count: " << sb1->getDataCount() << std::endl;

		StrBlob sb2 = *sb1;
		std::cout << "shared_ptr's count: " << sb1->getDataCount() << std::endl;
	}
	std::cout << "shared_ptr's count: " << sb1->getDataCount() << std::endl;
	delete sb1;
}

class numbered
{
public:
	numbered():mysn(0) {};
	numbered(int i):mysn(i + 2020) {}
	numbered(const numbered &i):mysn(i.mysn + 2020) {}
	numbered &operator=(const numbered &i) {mysn = i.mysn;}
	int getMysn() const {return mysn;}

private:
	// 类内数据成员不会执行默认初始化
	int mysn;
};

void f(numbered i)
{
	std::cout << i.getMysn() << std::endl;
}

void t13_17()
{
	numbered a, b = a, c = b;
	f(a); f(b); f(c);
}

void t13_27()
{
	// 实现了自己的引用计数， HasPtr
}

class TreeNode {

public:
	TreeNode(): value(std::string()), count(1), left(nullptr), right(nullptr) { }
	TreeNode(const TreeNode &node): value(node.value), count(node.count), left(node.left), right(node.right)
	{
		// 拷贝构造函数
	}
	TreeNode &operator=(const TreeNode &node)
	{
		// 重载赋值运算符
		value = node.value;
		count = node.count;
		delete left;
		delete right;
		left = node.left;
		right = node.right;
	}
	~TreeNode()
	{
		// 析构函数
		delete left;
		delete right;
	}


private:
	std::string value;
	int count;
	TreeNode *left;
	TreeNode *right;
};

class BinStrTree {

public:
	BinStrTree(): root(new TreeNode()) {}

	BinStrTree(const BinStrTree &btree): root(new TreeNode(*root))
	{
		// 拷贝构造函数
	}

	BinStrTree &operator=(const BinStrTree &btree)
	{
		auto *new_root = new TreeNode(*btree.root);
		delete root;
		root = new_root;
	}

	~BinStrTree() { delete root; }

private:
	TreeNode *root;
};

void t13_30()
{
	// 测试HasPtr
	HasPtr hp1("Hello world");
	HasPtr hp2("Hello cpp");
	swap(hp1, hp2);
	printPtr(hp1);
	printPtr(hp2);
	hp1 = hp2;  // 调用swap
}

void print_Folders(Folder &f)
{
	for (Message *m: f.get_msgs())
		m->print();
}

void messageAndFolder()
{
	std::cout << "begin" << std::endl;
	Message m1("Today is sunny!");
	Message m2("Today is cloudy!");
	Message m3("Today is rainy!");
	Message m4("Today is hot!");
	Message m5("Today is cold!");
	std::cout << "message over" << std::endl;
	Folder f1("Weather");
	std::cout << "Folder definition" << std::endl;
	m1.addFolder(f1);
	std::cout << "addFolder" << std::endl;
	m2.addFolder(f1);
	m3.addFolder(f1);
	m4.addFolder(f1);
	m5.addFolder(f1);

	print_Folders(f1);
	m1.remFolder(f1);
	std::cout << "delete sunny!" << std::endl;
	print_Folders(f1);
	std::cout << "over" << std::endl;
}

void t13_42()
{
	/*
	 * 测试StrVec
	 */
	StrVec strV;
	strV.push_back("hello world");
	strV.push_back("hello java");
	strV.resize(5, "hello cpp");
	strV.print();
}

void t13_44()
{
	/*
	 * string的简单版本实现
	 */
	String s("Hello world!");
	s.print();
}

void t13_48()
{
	std::vector<String> Svec;
	Svec.reserve(2);  // 加上这句话，就是一次了
	String s1 = String("hello cpp!");

	std::cout << "----------------" << std::endl;
	for (int i = 0; i < 5; ++i)
	{
		std::cout << "----------------" << i << "-------------" << std::endl;
//		Svec.push_back(String("hello cpp!"));
		Svec.push_back(s1);  // 这里涉及到重新分配内存 调用移动构造
	}
}

void t13_50()
{
  String s0;
  String s1("hello");
  String s2(s1);
  String s3 = s1;
  s2 = s1;

  std::vector<String> svec;
	std::cout << "2 ---------- " << std::endl;

  svec.push_back(s0);
  svec.push_back(s1);
  std::cout << "3 ---------- " << std::endl;
  svec.push_back("good job");
}

void t13_55()
{
	StrBlob sb({"hello world!"});
	sb.push_back("hello cpp!");
}

void t13_58()
{
	Foo f1({4,5,6,3,2,1,5,6,8,76});
	std::for_each(f1.begin(), f1.end(),  [](const int &i){ std::cout << i << " ";});
	Foo f2(f1.sorted());
	std::for_each(f2.begin(), f2.end(),  [](const int &i){ std::cout << i << " ";});
//	std::for_each(f1.sorted().begin(), f1.sorted().end(), [](const int &i){ std::cout << i << " "; });
}

int main13()
{

	std::cout << "-----------------拷贝构造函数----------------" << std::endl;
	t13_3();
	std::cout << "-----------------重载赋值运算符----------------" << std::endl;
	t13_7();

	std::cout << "-----------------析构函数----------------" << std::endl;
	t13_10();
	t13_17();

	std::cout << "-----------------拷贝控制和资源管理----------------" << std::endl;
	t13_27();

	std::cout << "-----------------交换操作swap----------------" << std::endl;
	t13_30();

	std::cout << "-----------------拷贝控制实例(Message/Folder)----------------" << std::endl;
//	messageAndFolder();  // 不知道是什么问题, 也没有报错信息， 反正就是无法到下一行
	std::cout << std::endl;

	std::cout << "-----------------动态内存管理类----------------" << std::endl;
	t13_42();
	t13_44();
	std::cout << std::endl;

	std::cout << "-----------------对象移动----------------" << std::endl;
	t13_48();
	t13_50();

	std::cout << "-------------右值引用和成员函数----------------" << std::endl;
	t13_55();

	std::cout << "-------------重载和引用函数----------------" << std::endl;
	t13_58();

	return 0;
}



